#include <QDateTime>
#include "container-helper.h"
#include "hierarchical-header-view.h"
#include "sort-filter-proxy-model.h"

SortFilterProxyModel::SortFilterProxyModel (QObject *parent) :
    QSortFilterProxyModel(parent), m_sortNumerical(false)
{
    setDynamicSortFilter(true);
}

bool SortFilterProxyModel::isSortNumerical() const
{
    return m_sortNumerical;
}

bool SortFilterProxyModel::isSortNumerical (int column) const
{
    return m_sortNumericalHash.value(column, m_sortNumerical);
}

int SortFilterProxyModel::sortRole() const
{
    return QSortFilterProxyModel::sortRole();
}

int SortFilterProxyModel::sortRole (int column) const
{
    return m_sortRoleHash.value(column, sortRole());
}

QVariant SortFilterProxyModel::data (const QModelIndex &index, int role) const
{
    if (!index.isValid())
    {
        if (role == HierarchicalHeaderView::HorizontalHeaderDataRole
            || role == HierarchicalHeaderView::VerticalHeaderDataRole)
        {
            return QSortFilterProxyModel::data(index, role);
        }
        else
        {
            return QVariant();
        }
    }

    return QSortFilterProxyModel::data(index, role);
}

QVariant SortFilterProxyModel::headerData (int section, Qt::Orientation orientation, int role) const
{
    if (orientation == Qt::Vertical && role == Qt::DisplayRole && section >= 0 && section < rowCount())
        return section+1;

    return QSortFilterProxyModel::headerData(section, orientation, role);
}

void SortFilterProxyModel::setSortNumerical (bool enable)
{
    m_sortNumerical = enable;
}

void SortFilterProxyModel::setSortNumerical (bool enable, int column)
{
    m_sortNumericalHash.insert(column, enable);
}

void SortFilterProxyModel::setSortRole (int role)
{
    QSortFilterProxyModel::setSortRole(role);
}

void SortFilterProxyModel::setSortRole (int role, int column)
{
    m_sortRoleHash.insert(column, role);
}

void SortFilterProxyModel::clearColumnSortRoles()
{
    m_sortRoleHash.clear();
}

bool SortFilterProxyModel::lessThan (const QModelIndex& left, const QModelIndex& right) const
{
    Q_ASSERT(left.isValid());
    Q_ASSERT(right.isValid());
    Q_ASSERT(left.column() == right.column());
    int sortRole = this->sortRole(left.column());
    QVariant leftValue = left.data(sortRole);
    QVariant rightValue = right.data(sortRole);

    switch (leftValue.userType())
    {
    case QVariant::Invalid:
        return (rightValue.type() != QVariant::Invalid);
    case QVariant::Int:
        return leftValue.toInt() < rightValue.toInt();
    case QVariant::UInt:
        return leftValue.toUInt() < rightValue.toUInt();
    case QVariant::LongLong:
        return leftValue.toLongLong() < rightValue.toLongLong();
    case QVariant::ULongLong:
        return leftValue.toULongLong() < rightValue.toULongLong();
    case QMetaType::Float:
        return leftValue.toFloat() < rightValue.toFloat();
    case QVariant::Double:
        return leftValue.toDouble() < rightValue.toDouble();
    case QVariant::Char:
        return leftValue.toChar() < rightValue.toChar();
    case QVariant::Date:
        return leftValue.toDate() < rightValue.toDate();
    case QVariant::Time:
        return leftValue.toTime() < rightValue.toTime();
    case QVariant::DateTime:
        return leftValue.toDateTime() < rightValue.toDateTime();
    case QVariant::String:
    default:
        if (isSortNumerical(left.column()))
        {
            return StringNumericalLess(sortCaseSensitivity(), isSortLocaleAware())
                   .operator()(leftValue.toString(), rightValue.toString());
        }
        else
        {
            if (isSortLocaleAware())
                return leftValue.toString().localeAwareCompare(rightValue.toString()) < 0;
            else
                return leftValue.toString().compare(rightValue.toString(), sortCaseSensitivity()) < 0;
        }
    }
    return false;
}
